home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 001-100 / 001-025 / 006 / microemacs / window.c < prev    next >
C/C++ Source or Header  |  1995-03-17  |  12KB  |  378 lines

  1.  
  2. /*
  3.  * Window management. Some of the functions are internal, and some are
  4.  * attached to keys that the user actually types.
  5.  */
  6.  
  7. #include        <stdio.h>
  8. #include        "ed.h"
  9.  
  10. /*
  11.  * Reposition dot in the current window to line "n". If the argument is
  12.  * positive, it is that line. If it is negative it is that line from the
  13.  * bottom. If it is 0 the window is centered (this is what the standard
  14.  * redisplay code does). With no argument it defaults to 1. Bound to M-!.
  15.  * Because of the default, it works like in Gosling.
  16.  */
  17. reposition(f, n)
  18.     {
  19.     curwp->w_force = n;
  20.     curwp->w_flag |= WFFORCE;
  21.     return (TRUE);
  22.     }
  23.  
  24. /*
  25.  * Refresh the screen. With no argument, it just does the refresh. With an
  26.  * argument it recenters "." in the current window. Bound to "C-L".
  27.  */
  28. refresh(f, n)
  29.     {
  30.     if (f == FALSE)
  31.         sgarbf = TRUE;
  32.     else
  33.         {
  34.         curwp->w_force = 0;             /* Center dot. */
  35.         curwp->w_flag |= WFFORCE;
  36.         }
  37.  
  38.     return (TRUE);
  39.     }
  40.  
  41. /*
  42.  * The command make the next window (next => down the screen) the current
  43.  * window. There are no real errors, although the command does nothing if
  44.  * there is only 1 window on the screen. Bound to "C-X C-N".
  45.  */
  46. nextwind(f, n)
  47.     {
  48.     register WINDOW *wp;
  49.  
  50.     if ((wp = curwp->w_wndp) == NULL)
  51.         wp = wheadp;
  52.  
  53.     curwp = wp;
  54.     curbp = wp->w_bufp;
  55.     return (TRUE);
  56.     }
  57.  
  58. /*
  59.  * This command makes the previous window (previous => up the screen) the
  60.  * current window. There arn't any errors, although the command does not do a
  61.  * lot if there is 1 window.
  62.  */
  63. prevwind(f, n)
  64.     {
  65.     register WINDOW *wp1;
  66.     register WINDOW *wp2;
  67.  
  68.     wp1 = wheadp;
  69.     wp2 = curwp;
  70.  
  71.     if (wp1 == wp2)
  72.         wp2 = NULL;
  73.  
  74.     while (wp1->w_wndp != wp2)
  75.         wp1 = wp1->w_wndp;
  76.  
  77.     curwp = wp1;
  78.     curbp = wp1->w_bufp;
  79.     return (TRUE);
  80.     }
  81.  
  82. /*
  83.  * This command moves the current window down by "arg" lines. Recompute the
  84.  * top line in the window. The move up and move down code is almost completely
  85.  * the same; most of the work has to do with reframing the window, and picking
  86.  * a new dot. We share the code by having "move down" just be an interface to
  87.  * "move up". Magic. Bound to "C-X C-N".
  88.  */
  89. mvdnwind(f, n)
  90.     int n;
  91.     {
  92.     return (mvupwind(f, -n));
  93.     }
  94.  
  95. /*
  96.  * Move the current window up by "arg" lines. Recompute the new top line of
  97.  * the window. Look to see if "." is still on the screen. If it is, you win.
  98.  * If it isn't, then move "." to center it in the new framing of the window
  99.  * (this command does not really move "."; it moves the frame). Bound to
  100.  * "C-X C-P".
  101.  */
  102. mvupwind(f, n)
  103.     int n;
  104.     {
  105.     register LINE *lp;
  106.     register int i;
  107.  
  108.     lp = curwp->w_linep;
  109.  
  110.     if (n < 0)
  111.         {
  112.         while (n++ && lp!=curbp->b_linep)
  113.             lp = lforw(lp);
  114.         }
  115.     else
  116.         {
  117.         while (n-- && lback(lp)!=curbp->b_linep)
  118.             lp = lback(lp);
  119.         }
  120.  
  121.     curwp->w_linep = lp;
  122.     curwp->w_flag |= WFHARD;            /* Mode line is OK. */
  123.  
  124.     for (i = 0; i < curwp->w_ntrows; ++i)
  125.         {
  126.         if (lp == curwp->w_dotp)
  127.             return (TRUE);
  128.         if (lp == curbp->b_linep)
  129.             break;
  130.         lp = lforw(lp);
  131.         }
  132.  
  133.     lp = curwp->w_linep;
  134.     i  = curwp->w_ntrows/2;
  135.  
  136.     while (i-- && lp != curbp->b_linep)
  137.         lp = lforw(lp);
  138.  
  139.     curwp->w_dotp  = lp;
  140.     curwp->w_doto  = 0;
  141.     return (TRUE);
  142.     }
  143.  
  144. /*
  145.  * This command makes the current window the only window on the screen. Bound
  146.  * to "C-X 1". Try to set the framing so that "." does not have to move on the
  147.  * display. Some care has to be taken to keep the values of dot and mark in
  148.  * the buffer structures right if the distruction of a window makes a buffer
  149.  * become undisplayed.
  150.  */
  151. onlywind(f, n)
  152. {
  153.         register WINDOW *wp;
  154.         register LINE   *lp;
  155.         register int    i;
  156.  
  157.         while (wheadp != curwp) {
  158.                 wp = wheadp;
  159.                 wheadp = wp->w_wndp;
  160.                 if (--wp->w_bufp->b_nwnd == 0) {
  161.                         wp->w_bufp->b_dotp  = wp->w_dotp;
  162.                         wp->w_bufp->b_doto  = wp->w_doto;
  163.                         wp->w_bufp->b_markp = wp->w_markp;
  164.                         wp->w_bufp->b_marko = wp->w_marko;
  165.                 }
  166.                 free((char *) wp);
  167.         }
  168.         while (curwp->w_wndp != NULL) {
  169.                 wp = curwp->w_wndp;
  170.                 curwp->w_wndp = wp->w_wndp;
  171.                 if (--wp->w_bufp->b_nwnd == 0) {
  172.                         wp->w_bufp->b_dotp  = wp->w_dotp;
  173.                         wp->w_bufp->b_doto  = wp->w_doto;
  174.                         wp->w_bufp->b_markp = wp->w_markp;
  175.                         wp->w_bufp->b_marko = wp->w_marko;
  176.                 }
  177.                 free((char *) wp);
  178.         }
  179.         lp = curwp->w_linep;
  180.         i  = curwp->w_toprow;
  181.         while (i!=0 && lback(lp)!=curbp->b_linep) {
  182.                 --i;
  183.                 lp = lback(lp);
  184.         }
  185.         curwp->w_toprow = 0;
  186.         curwp->w_ntrows = term.t_nrow-1;
  187.         curwp->w_linep  = lp;
  188.         curwp->w_flag  |= WFMODE|WFHARD;
  189.         return (TRUE);
  190. }
  191.  
  192. /*
  193.  * Split the current window. A window smaller than 3 lines cannot be split.
  194.  * The only other error that is possible is a "malloc" failure allocating the
  195.  * structure for the new window. Bound to "C-X 2".
  196.  */
  197. splitwind(f, n)
  198. {
  199.         register WINDOW *wp;
  200.         register LINE   *lp;
  201.         register int    ntru;
  202.         register int    ntrl;
  203.         register int    ntrd;
  204.         register WINDOW *wp1;
  205.         register WINDOW *wp2;
  206.  
  207.         if (curwp->w_ntrows < 3) {
  208.                 mlwrite("Cannot split a %d line window", curwp->w_ntrows);
  209.                 return (FALSE);
  210.         }
  211.         if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) {
  212.                 mlwrite("Cannot allocate WINDOW block");
  213.                 return (FALSE);
  214.         }
  215.         ++curbp->b_nwnd;                        /* Displayed twice.     */
  216.         wp->w_bufp  = curbp;
  217.         wp->w_dotp  = curwp->w_dotp;
  218.         wp->w_doto  = curwp->w_doto;
  219.         wp->w_markp = curwp->w_markp;
  220.         wp->w_marko = curwp->w_marko;
  221.         wp->w_flag  = 0;
  222.         wp->w_force = 0;
  223.         ntru = (curwp->w_ntrows-1) / 2;         /* Upper size           */
  224.         ntrl = (curwp->w_ntrows-1) - ntru;      /* Lower size           */
  225.         lp = curwp->w_linep;
  226.         ntrd = 0;
  227.         while (lp != curwp->w_dotp) {
  228.                 ++ntrd;
  229.                 lp = lforw(lp);
  230.         }
  231.         lp = curwp->w_linep;
  232.         if (ntrd <= ntru) {                     /* Old is upper window. */
  233.                 if (ntrd == ntru)               /* Hit mode line.       */
  234.                         lp = lforw(lp);
  235.                 curwp->w_ntrows = ntru;
  236.                 wp->w_wndp = curwp->w_wndp;
  237.                 curwp->w_wndp = wp;
  238.                 wp->w_toprow = curwp->w_toprow+ntru+1;
  239.                 wp->w_ntrows = ntrl;
  240.         } else {                                /* Old is lower window  */
  241.                 wp1 = NULL;
  242.                 wp2 = wheadp;
  243.                 while (wp2 != curwp) {
  244.                         wp1 = wp2;
  245.                         wp2 = wp2->w_wndp;
  246.                 }
  247.                 if (wp1 == NULL)
  248.                         wheadp = wp;
  249.                 else
  250.                         wp1->w_wndp = wp;
  251.                 wp->w_wndp   = curwp;
  252.                 wp->w_toprow = curwp->w_toprow;
  253.                 wp->w_ntrows = ntru;
  254.                 ++ntru;                         /* Mode line.           */
  255.                 curwp->w_toprow += ntru;
  256.                 curwp->w_ntrows  = ntrl;
  257.                 while (ntru--)
  258.                         lp = lforw(lp);
  259.         }
  260.         curwp->w_linep = lp;                    /* Adjust the top lines */
  261.         wp->w_linep = lp;                       /* if necessary.        */
  262.         curwp->w_flag |= WFMODE|WFHARD;
  263.         wp->w_flag |= WFMODE|WFHARD;
  264.         return (TRUE);
  265. }
  266.  
  267. /*
  268.  * Enlarge the current window. Find the window that loses space. Make sure it
  269.  * is big enough. If so, hack the window descriptions, and ask redisplay to do
  270.  * all the hard work. You don't just set "force reframe" because dot would
  271.  * move. Bound to "C-X Z".
  272.  */
  273. enlargewind(f, n)
  274. {
  275.         register WINDOW *adjwp;
  276.         register LINE   *lp;
  277.         register int    i;
  278.  
  279.         if (n < 0)
  280.                 return (shrinkwind(f, -n));
  281.         if (wheadp->w_wndp == NULL) {
  282.                 mlwrite("Only one window");
  283.                 return (FALSE);
  284.         }
  285.         if ((adjwp=curwp->w_wndp) == NULL) {
  286.                 adjwp = wheadp;
  287.                 while (adjwp->w_wndp != curwp)
  288.                         adjwp = adjwp->w_wndp;
  289.         }
  290.         if (adjwp->w_ntrows <= n) {
  291.                 mlwrite("Impossible change");
  292.                 return (FALSE);
  293.         }
  294.         if (curwp->w_wndp == adjwp) {           /* Shrink below.        */
  295.                 lp = adjwp->w_linep;
  296.                 for (i=0; i<n && lp!=adjwp->w_bufp->b_linep; ++i)
  297.                         lp = lforw(lp);
  298.                 adjwp->w_linep  = lp;
  299.                 adjwp->w_toprow += n;
  300.         } else {                                /* Shrink above.        */
  301.                 lp = curwp->w_linep;
  302.                 for (i=0; i<n && lback(lp)!=curbp->b_linep; ++i)
  303.                         lp = lback(lp);
  304.                 curwp->w_linep  = lp;
  305.                 curwp->w_toprow -= n;
  306.         }
  307.         curwp->w_ntrows += n;
  308.         adjwp->w_ntrows -= n;
  309.         curwp->w_flag |= WFMODE|WFHARD;
  310.         adjwp->w_flag |= WFMODE|WFHARD;
  311.         return (TRUE);
  312. }
  313.  
  314. /*
  315.  * Shrink the current window. Find the window that gains space. Hack at the
  316.  * window descriptions. Ask the redisplay to do all the hard work. Bound to
  317.  * "C-X C-Z".
  318.  */
  319. shrinkwind(f, n)
  320. {
  321.         register WINDOW *adjwp;
  322.         register LINE   *lp;
  323.         register int    i;
  324.  
  325.         if (n < 0)
  326.                 return (enlargewind(f, -n));
  327.         if (wheadp->w_wndp == NULL) {
  328.                 mlwrite("Only one window");
  329.                 return (FALSE);
  330.         }
  331.         if ((adjwp=curwp->w_wndp) == NULL) {
  332.                 adjwp = wheadp;
  333.                 while (adjwp->w_wndp != curwp)
  334.                         adjwp = adjwp->w_wndp;
  335.         }
  336.         if (curwp->w_ntrows <= n) {
  337.                 mlwrite("Impossible change");
  338.                 return (FALSE);
  339.         }
  340.         if (curwp->w_wndp == adjwp) {           /* Grow below.          */
  341.                 lp = adjwp->w_linep;
  342.                 for (i=0; i<n && lback(lp)!=adjwp->w_bufp->b_linep; ++i)
  343.                         lp = lback(lp);
  344.                 adjwp->w_linep  = lp;
  345.                 adjwp->w_toprow -= n;
  346.         } else {                                /* Grow above.          */
  347.                 lp = curwp->w_linep;
  348.                 for (i=0; i<n && lp!=curbp->b_linep; ++i)
  349.                         lp = lforw(lp);
  350.                 curwp->w_linep  = lp;
  351.                 curwp->w_toprow += n;
  352.         }
  353.         curwp->w_ntrows -= n;
  354.         adjwp->w_ntrows += n;
  355.         curwp->w_flag |= WFMODE|WFHARD;
  356.         adjwp->w_flag |= WFMODE|WFHARD;
  357.         return (TRUE);
  358. }
  359.  
  360. /*
  361.  * Pick a window for a pop-up. Split the screen if there is only one window.
  362.  * Pick the uppermost window that isn't the current window. An LRU algorithm
  363.  * might be better. Return a pointer, or NULL on error.
  364.  */
  365. WINDOW  *
  366. wpopup()
  367. {
  368.         register WINDOW *wp;
  369.  
  370.         if (wheadp->w_wndp == NULL              /* Only 1 window        */
  371.         && splitwind(FALSE, 0) == FALSE)        /* and it won't split   */
  372.                 return (NULL);
  373.         wp = wheadp;                            /* Find window to use   */
  374.         while (wp!=NULL && wp==curwp)
  375.                 wp = wp->w_wndp;
  376.         return (wp);
  377. }
  378.